//! # RBAC（基于角色的访问控制）测试
//!
//! 测试企业级RBAC功能的完整性和正确性

use std::sync::Arc;
use std::collections::HashMap;
use tokio;
use rustcloud_auth::prelude::*;

#[cfg(feature = "rbac")]
use rustcloud_auth::rbac::{RoleManager, PermissionManager, PolicyEngine, AccessPolicy, PolicyRule, ResourcePattern};

#[cfg(feature = "rbac")]
mod rbac_tests {
    use super::*;

    /// 测试角色管理器
    #[tokio::test]
    async fn test_role_manager() {
        let role_manager = RoleManager::new();

        // 创建角色
        let admin_role = Role::new("admin".to_string(), "Administrator".to_string())
            .add_permission("*".to_string());
        
        let user_role = Role::new("user".to_string(), "Regular User".to_string())
            .add_permission("read:posts".to_string())
            .add_permission("write:comments".to_string());

        let editor_role = Role::new("editor".to_string(), "Content Editor".to_string())
            .add_permission("read:posts".to_string())
            .add_permission("write:posts".to_string())
            .add_permission("edit:posts".to_string());

        // 添加角色
        role_manager.create_role(admin_role.clone()).await.unwrap();
        role_manager.create_role(user_role.clone()).await.unwrap();
        role_manager.create_role(editor_role.clone()).await.unwrap();

        // 验证角色创建
        let retrieved_admin = role_manager.get_role("admin").await.unwrap();
        assert!(retrieved_admin.is_some());
        assert_eq!(retrieved_admin.unwrap().name, "admin");

        // 测试角色层次结构
        role_manager.add_role_parent("editor", "user").await.unwrap();
        let parents = role_manager.get_role_parents("editor").await.unwrap();
        assert!(parents.contains(&"user".to_string()));

        // 测试有效角色获取
        let effective_roles = role_manager.get_effective_roles("editor").await.unwrap();
        assert!(effective_roles.contains(&"editor".to_string()));
        assert!(effective_roles.contains(&"user".to_string()));
    }

    /// 测试权限管理器
    #[tokio::test]
    async fn test_permission_manager() {
        let permission_manager = PermissionManager::new();

        // 创建权限
        let read_posts = Permission::new("read:posts".to_string(), "Read posts".to_string());
        let write_posts = Permission::new("write:posts".to_string(), "Write posts".to_string());
        let delete_posts = Permission::new("delete:posts".to_string(), "Delete posts".to_string());

        permission_manager.create_permission(read_posts).await.unwrap();
        permission_manager.create_permission(write_posts).await.unwrap();
        permission_manager.create_permission(delete_posts).await.unwrap();

        // 验证权限创建
        let retrieved_permission = permission_manager.get_permission("read:posts").await.unwrap();
        assert!(retrieved_permission.is_some());
        assert_eq!(retrieved_permission.unwrap().name, "read:posts");

        // 测试权限层次结构
        permission_manager.add_permission_parent("write:posts", "read:posts").await.unwrap();
        let parents = permission_manager.get_permission_parents("write:posts").await.unwrap();
        assert!(parents.contains(&"read:posts".to_string()));

        // 测试有效权限获取
        let effective_permissions = permission_manager.get_effective_permissions("write:posts").await.unwrap();
        assert!(effective_permissions.contains(&"write:posts".to_string()));
        assert!(effective_permissions.contains(&"read:posts".to_string()));
    }

    /// 测试策略引擎
    #[tokio::test]
    async fn test_policy_engine() {
        let role_manager = Arc::new(RoleManager::new());
        let permission_manager = Arc::new(PermissionManager::new());
        let policy_engine = PolicyEngine::new(role_manager.clone(), permission_manager.clone());

        // 创建基础角色和权限
        let admin_role = Role::new("admin".to_string(), "Administrator".to_string())
            .add_permission("*".to_string());
        let user_role = Role::new("user".to_string(), "Regular User".to_string())
            .add_permission("read:posts".to_string());

        role_manager.create_role(admin_role).await.unwrap();
        role_manager.create_role(user_role).await.unwrap();

        let read_permission = Permission::new("read:posts".to_string(), "Read posts".to_string());
        let write_permission = Permission::new("write:posts".to_string(), "Write posts".to_string());

        permission_manager.create_permission(read_permission).await.unwrap();
        permission_manager.create_permission(write_permission).await.unwrap();

        // 创建用户主体
        let admin_principal = Principal::new(
            "admin_user".to_string(),
            "Admin User".to_string(),
            PrincipalType::User,
        ).add_role("admin".to_string());

        let regular_principal = Principal::new(
            "regular_user".to_string(),
            "Regular User".to_string(),
            PrincipalType::User,
        ).add_role("user".to_string());

        // 创建资源
        let posts_resource = Resource::new(
            "blog-service".to_string(),
            "/api/posts".to_string(),
            "GET".to_string(),
        );

        let admin_posts_resource = Resource::new(
            "admin-service".to_string(),
            "/api/admin/posts".to_string(),
            "DELETE".to_string(),
        );

        // 测试管理员访问
        let admin_result = policy_engine.evaluate(&admin_principal, &posts_resource, HashMap::new()).await.unwrap();
        assert!(admin_result.allowed);

        let admin_delete_result = policy_engine.evaluate(&admin_principal, &admin_posts_resource, HashMap::new()).await.unwrap();
        assert!(admin_delete_result.allowed);

        // 测试普通用户访问
        let user_result = policy_engine.evaluate(&regular_principal, &posts_resource, HashMap::new()).await.unwrap();
        assert!(user_result.allowed); // 应该有读取权限

        let user_delete_result = policy_engine.evaluate(&regular_principal, &admin_posts_resource, HashMap::new()).await.unwrap();
        assert!(!user_delete_result.allowed); // 不应该有删除权限
    }

    /// 测试基于时间的访问控制
    #[tokio::test]
    async fn test_time_based_access_control() {
        let role_manager = Arc::new(RoleManager::new());
        let permission_manager = Arc::new(PermissionManager::new());
        let mut policy_engine = PolicyEngine::new(role_manager.clone(), permission_manager.clone());

        // 创建基础设置
        let user_role = Role::new("user".to_string(), "Regular User".to_string())
            .add_permission("read:posts".to_string());
        role_manager.create_role(user_role).await.unwrap();

        let principal = Principal::new(
            "test_user".to_string(),
            "Test User".to_string(),
            PrincipalType::User,
        ).add_role("user".to_string());

        let resource = Resource::new(
            "blog-service".to_string(),
            "/api/posts".to_string(),
            "GET".to_string(),
        );

        // 创建基于时间的策略
        let time_policy = AccessPolicy {
            id: "time_restricted".to_string(),
            name: "Time Restricted Access".to_string(),
            description: "Only allow access during business hours".to_string(),
            resource_patterns: vec![ResourcePattern {
                service: Some("blog-service".to_string()),
                path_pattern: Some("/api/posts".to_string()),
                method: Some("GET".to_string()),
            }],
            rules: vec![PolicyRule {
                effect: "allow".to_string(),
                conditions: vec![
                    "time_hour >= 9".to_string(),
                    "time_hour <= 17".to_string(),
                ],
                description: "Allow access during business hours (9 AM - 5 PM)".to_string(),
            }],
            priority: 10,
            enabled: true,
        };

        policy_engine.add_policy(time_policy).await.unwrap();

        // 测试工作时间内的访问（假设是下午2点）
        let mut context = HashMap::new();
        context.insert("time_hour".to_string(), "14".to_string());

        let result = policy_engine.evaluate(&principal, &resource, context).await.unwrap();
        assert!(result.allowed);

        // 测试工作时间外的访问（假设是晚上8点）
        let mut context = HashMap::new();
        context.insert("time_hour".to_string(), "20".to_string());

        let result = policy_engine.evaluate(&principal, &resource, context).await.unwrap();
        assert!(!result.allowed);
    }

    /// 测试基于IP的访问控制
    #[tokio::test]
    async fn test_ip_based_access_control() {
        let role_manager = Arc::new(RoleManager::new());
        let permission_manager = Arc::new(PermissionManager::new());
        let mut policy_engine = PolicyEngine::new(role_manager.clone(), permission_manager.clone());

        // 创建基础设置
        let admin_role = Role::new("admin".to_string(), "Administrator".to_string())
            .add_permission("admin:*".to_string());
        role_manager.create_role(admin_role).await.unwrap();

        let principal = Principal::new(
            "admin_user".to_string(),
            "Admin User".to_string(),
            PrincipalType::User,
        ).add_role("admin".to_string());

        let resource = Resource::new(
            "admin-service".to_string(),
            "/api/admin/users".to_string(),
            "DELETE".to_string(),
        );

        // 创建基于IP的策略
        let ip_policy = AccessPolicy {
            id: "ip_restricted".to_string(),
            name: "IP Restricted Access".to_string(),
            description: "Only allow admin access from internal IPs".to_string(),
            resource_patterns: vec![ResourcePattern {
                service: Some("admin-service".to_string()),
                path_pattern: Some("/api/admin/*".to_string()),
                method: None,
            }],
            rules: vec![PolicyRule {
                effect: "allow".to_string(),
                conditions: vec![
                    "client_ip.startsWith('192.168.')".to_string(),
                ],
                description: "Allow admin access only from internal network".to_string(),
            }],
            priority: 20,
            enabled: true,
        };

        policy_engine.add_policy(ip_policy).await.unwrap();

        // 测试内网IP访问
        let mut context = HashMap::new();
        context.insert("client_ip".to_string(), "192.168.1.100".to_string());

        let result = policy_engine.evaluate(&principal, &resource, context).await.unwrap();
        assert!(result.allowed);

        // 测试外网IP访问
        let mut context = HashMap::new();
        context.insert("client_ip".to_string(), "203.0.113.1".to_string());

        let result = policy_engine.evaluate(&principal, &resource, context).await.unwrap();
        assert!(!result.allowed);
    }

    /// 测试复杂策略组合
    #[tokio::test]
    async fn test_complex_policy_combination() {
        let role_manager = Arc::new(RoleManager::new());
        let permission_manager = Arc::new(PermissionManager::new());
        let mut policy_engine = PolicyEngine::new(role_manager.clone(), permission_manager.clone());

        // 创建角色层次结构
        let admin_role = Role::new("admin".to_string(), "Administrator".to_string())
            .add_permission("*".to_string());
        let manager_role = Role::new("manager".to_string(), "Manager".to_string())
            .add_permission("manage:team".to_string());
        let employee_role = Role::new("employee".to_string(), "Employee".to_string())
            .add_permission("read:documents".to_string());

        role_manager.create_role(admin_role).await.unwrap();
        role_manager.create_role(manager_role).await.unwrap();
        role_manager.create_role(employee_role).await.unwrap();

        // 设置角色继承
        role_manager.add_role_parent("manager", "employee").await.unwrap();

        let manager_principal = Principal::new(
            "manager_user".to_string(),
            "Manager User".to_string(),
            PrincipalType::User,
        ).add_role("manager".to_string());

        let sensitive_resource = Resource::new(
            "hr-service".to_string(),
            "/api/hr/salaries".to_string(),
            "GET".to_string(),
        );

        // 创建多层策略
        let sensitive_data_policy = AccessPolicy {
            id: "sensitive_data".to_string(),
            name: "Sensitive Data Access".to_string(),
            description: "Restrict access to sensitive data".to_string(),
            resource_patterns: vec![ResourcePattern {
                service: Some("hr-service".to_string()),
                path_pattern: Some("/api/hr/salaries".to_string()),
                method: Some("GET".to_string()),
            }],
            rules: vec![
                PolicyRule {
                    effect: "allow".to_string(),
                    conditions: vec![
                        "principal.roles.contains('manager')".to_string(),
                        "time_hour >= 9".to_string(),
                        "time_hour <= 17".to_string(),
                        "client_ip.startsWith('192.168.')".to_string(),
                    ],
                    description: "Allow managers to access salary data during business hours from internal network".to_string(),
                },
                PolicyRule {
                    effect: "deny".to_string(),
                    conditions: vec![
                        "!client_ip.startsWith('192.168.')".to_string(),
                    ],
                    description: "Deny access from external networks".to_string(),
                },
            ],
            priority: 30,
            enabled: true,
        };

        policy_engine.add_policy(sensitive_data_policy).await.unwrap();

        // 测试符合所有条件的访问
        let mut context = HashMap::new();
        context.insert("time_hour".to_string(), "14".to_string());
        context.insert("client_ip".to_string(), "192.168.1.50".to_string());

        let result = policy_engine.evaluate(&manager_principal, &sensitive_resource, context).await.unwrap();
        assert!(result.allowed);

        // 测试违反时间条件的访问
        let mut context = HashMap::new();
        context.insert("time_hour".to_string(), "22".to_string());
        context.insert("client_ip".to_string(), "192.168.1.50".to_string());

        let result = policy_engine.evaluate(&manager_principal, &sensitive_resource, context).await.unwrap();
        assert!(!result.allowed);

        // 测试违反IP条件的访问
        let mut context = HashMap::new();
        context.insert("time_hour".to_string(), "14".to_string());
        context.insert("client_ip".to_string(), "203.0.113.1".to_string());

        let result = policy_engine.evaluate(&manager_principal, &sensitive_resource, context).await.unwrap();
        assert!(!result.allowed);
    }

    /// 测试策略优先级
    #[tokio::test]
    async fn test_policy_priority() {
        let role_manager = Arc::new(RoleManager::new());
        let permission_manager = Arc::new(PermissionManager::new());
        let mut policy_engine = PolicyEngine::new(role_manager.clone(), permission_manager.clone());

        let user_role = Role::new("user".to_string(), "Regular User".to_string())
            .add_permission("read:posts".to_string());
        role_manager.create_role(user_role).await.unwrap();

        let principal = Principal::new(
            "test_user".to_string(),
            "Test User".to_string(),
            PrincipalType::User,
        ).add_role("user".to_string());

        let resource = Resource::new(
            "blog-service".to_string(),
            "/api/posts".to_string(),
            "GET".to_string(),
        );

        // 创建低优先级允许策略
        let allow_policy = AccessPolicy {
            id: "allow_all".to_string(),
            name: "Allow All".to_string(),
            description: "Allow all access".to_string(),
            resource_patterns: vec![ResourcePattern {
                service: Some("blog-service".to_string()),
                path_pattern: Some("/api/posts".to_string()),
                method: Some("GET".to_string()),
            }],
            rules: vec![PolicyRule {
                effect: "allow".to_string(),
                conditions: vec![],
                description: "Allow all access".to_string(),
            }],
            priority: 10,
            enabled: true,
        };

        // 创建高优先级拒绝策略
        let deny_policy = AccessPolicy {
            id: "deny_emergency".to_string(),
            name: "Emergency Deny".to_string(),
            description: "Emergency access denial".to_string(),
            resource_patterns: vec![ResourcePattern {
                service: Some("blog-service".to_string()),
                path_pattern: Some("/api/posts".to_string()),
                method: Some("GET".to_string()),
            }],
            rules: vec![PolicyRule {
                effect: "deny".to_string(),
                conditions: vec![],
                description: "Emergency denial".to_string(),
            }],
            priority: 20, // 更高优先级
            enabled: true,
        };

        policy_engine.add_policy(allow_policy).await.unwrap();
        policy_engine.add_policy(deny_policy).await.unwrap();

        // 高优先级的拒绝策略应该生效
        let result = policy_engine.evaluate(&principal, &resource, HashMap::new()).await.unwrap();
        assert!(!result.allowed);
    }
}